/*
 * Copyright (C) 2022 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include "taskbarmanager.h"
#include <QDateTime>
#include <QPixmap>
#include <QFile>
#include <kdesktopfile.h>
#include <QList>
#include <QThread>

TaskBarManager::TaskBarManager(ModelManager *parent)
    : QObject(parent)
    , m_taskbarModelManager(parent)
    , m_appManagerInterface(new ComKylinAppManagerInterface("com.kylin.AppManager",
                                                    "/com/kylin/AppManager",
                                                    QDBusConnection::sessionBus()))

{
    if (!m_appManagerInterface->isValid()) {
        qWarning() << "Connect to com.kylin.AppManager dbus service failed!"
                   << m_appManagerInterface->lastError();
    }
    initConnections();
}

void TaskBarManager::initConnections()
{
    connect(kdk::WindowManager::self(), &kdk::WindowManager::windowRemoved, this, &TaskBarManager::handleAppClosed);

    QDBusConnection::sessionBus().connect(QString("com.kylin.AppManager"),
                                          QString("/com/kylin/AppManager"),
                                          QString("com.kylin.AppManager"),
                                          QString("appLaunched"), this, SLOT(updateWindowOpenInformation(QString, qlonglong, uint)));
}

void TaskBarManager::setWindowDesktopFileName(quint32 wid, const QString &fileName)
{
    m_isOpenWindows[fileName].push_back(wid);
}

void TaskBarManager::updateWindowOpenInformation(QString desktopName, qlonglong pid, uint wid)
{
    using namespace kdk;
    qDebug() << "window open desktop,pid,wid" << desktopName << wid << pid;
    if (desktopName.isEmpty()) {
        qWarning() << "desktop is null";
        return;
    }
    if (!desktopName.endsWith(".desktop")) {
        desktopName = desktopName + ".desktop";
    }

    int counter = 0;
    while (!WindowManager::windows().contains(wid)) {
        if (counter > 5000) {
            qDebug() << __func__ << "Exit the cycle after exceeding the time!!!";
            break;
        }
        qApp->processEvents();
        ++counter;
        QThread::msleep(1);
    }

    bool pidExist = false;
    QList<WindowId> widList = WindowManager::windows();
    for (int i = 0; i < widList.count(); ++i) {
        if (WindowManager::getPid(widList[i]) == pid && widList.contains(wid)) {
            pidExist = true;
            break;
        }
    }
    if (!pidExist) {
        qDebug() << "pid is invalid" << wid << widList;
        return;
    }
    saveWindowWid(desktopName, wid);
}

void TaskBarManager::saveWindowWid(QString desktopName, int wid)
{
    QString desktopFileName = m_taskbarModelManager->findDesktopNameFromTaskbar(desktopName);
    if (desktopFileName.isEmpty()) {
        desktopFileName = m_taskbarModelManager->findDesktopName(desktopName);
        if (desktopFileName.isEmpty()) {
            qWarning() << __func__ << "desktopFileName not found !!!";
            return;
        }
        if (m_isOpenWindows.value(desktopName).contains(wid)) {
            return;
        }
        QString iconFileName = m_taskbarModelManager->findIconPath(desktopFileName);
        QString appName = m_taskbarModelManager->findAppName(desktopFileName);
        m_isOpenWindows[desktopName].push_back(wid);
        m_taskbarModelManager->addWindowIconToTaskbar(iconFileName, desktopFileName, appName, wid);
    } else {
        // 该应用在任务栏，设置为打开状态
        m_taskbarModelManager->setAppOpenState(desktopName, wid);
        if (m_isOpenWindows.value(desktopName).contains(wid)) {
            return;
        }
        m_isOpenWindows[desktopName].push_back(wid);
    }
}

void TaskBarManager::handleAppClosed(kdk::WindowId wid)
{
    qDebug() << "app close wid:" << wid.toUInt();
    for (auto widList = m_isOpenWindows.begin(); widList != m_isOpenWindows.end(); widList++) {
        for (auto j = 0; j < widList->count(); j++) {
            if (widList->at(j) != wid) {
                continue;
            }
            if (widList->count() == 1) {
                QString desktopName = widList.key();
                if (m_taskbarModelManager->findDesktopName(desktopName).isEmpty()) {
                    m_taskbarModelManager->setAppCloseState(desktopName);
                } else {
                    m_taskbarModelManager->removeAppIconFromTaskBar(desktopName);
                }
                m_isOpenWindows.erase(widList);
                return;
            } else {
                qDebug() << "remove window" <<widList->at(j);
                widList->removeAt(j);
                QString desktopName = widList.key();
                if (m_taskbarModelManager->findDesktopName(desktopName).isEmpty() &&
                        m_taskbarModelManager->findDesktopNameFromTaskbar(desktopName).isEmpty()) {
                    qWarning() << __func__ << "desktopname is not found";
                    return;
                }
                m_taskbarModelManager->changeAppWindowWid(desktopName, wid.toUInt(), widList->at(0));
                return;
            }
        }
    }
}
